import 'package:flutter_map_demo/t3_map_plugin/map/core/t3_location.dart';
import 'package:flutter_map_demo/t3_map_plugin/route/core/t3_route_model.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:t3_data_service/config/request/request.dart';
import 'package:t3_data_service/data_provider/map_sctx/t3_map_sctx_provider.dart';
import 'package:t3_foundation/t3_foundation.dart';
import 'package:t3_network/t3_network.dart';

part 't3_route_data_service.g.dart';

class T3RouteDataService {

  ///根据起终点，获取步行路线信息
  static Future<T3RouteModel?>getWalkRouteFromService({required T3LocationCoordinate2D origin, required T3LocationCoordinate2D destination}) async {

    final request = _WalkRouteCalculateRequest(origin: origin, destination: destination);
    try {
      final resp = await T3Network().send(request, fromJson: _RouteContainerTransformModel.fromJson);
      if (resp.isSuccess()) {
        if (resp.succcessValue?.data != null) {
          final value = (resp.succcessValue?.data)!;
          if (value.routes != null) {
            if (value.routes!.isEmpty == false) {
              final route = value.routes!.first;
              final provider = T3MapType.fromJson(value.supplier);
                
                String polyline = '';
                if (route.steps != null) {
                  if (route.steps!.isEmpty == false) {
                    for (var element in route.steps!) {
                      polyline = polyline + (element.polyline ?? '');
                    }
                  }
                }
                List<T3LocationCoordinate2D> coordinates = T3RouteModel.stringToCoordinate2D(polyline: polyline);
                final ret = T3RouteModel(
                                          routeId: null, 
                                          duration: route.duration ?? 60, 
                                          distance: route.distance ?? 0, 
                                          tolls: 0, 
                                          trafficLightCount: 0, 
                                          tag: null,
                                          subTag: null,
                                          coordinates: coordinates, 
                                          provider: provider
                                        );

                return ret;  

            } else {
              return null;
            }
          }
          else {
            return null;
          }
        }
        else {
          return null;
        }
      } else {
        return null;
      }
    } catch(e) {
      return null;
    }
  }

  /// 根据起终点，获取驾车路线信息
  /// 使用gis：notoken/ws/lbs/v2/route/eval/direction/driving接口进行请求，接口会默认重试3次
  static Future<T3RouteResultModel?>getGisRouteFromService({required T3MapType mapType,
    required T3LocationCoordinate2D origin,
    required T3LocationCoordinate2D destination,
    List<T3LocationCoordinate2D>? viaPoints,
    String? originPoiId,
    String? destPoiId,
    String? areaCode,
    double? departureTime,}) async {

    final request = _DrivingRouteCalculateRequest(
      origin: origin, dest: destination, waypoints: viaPoints, departureTime: departureTime, originPoiId: originPoiId, destPoiId: destPoiId, areaCode: areaCode
    );
    try {
      //接口超时时间10s，重试3次，间隔100ms
      const options = T3DefaultHTTPOptions(10, null, T3HTTPRetryTimes.three, 100);
      final resp = await T3Network().send(request, fromJson: _DriverRouteContainerTransformModel.fromJson, httpOptions: options);
      if (resp.isSuccess()) {
        if (resp.succcessValue?.data != null) {
          final value = (resp.succcessValue?.data)!;
          if (value.routes != null) {
            final routes = value.routes!;
            if (routes.isEmpty == false) {
              
              final T3MapType mapTypeValue;

              if (value.supplier != null && value.supplier == 3) {
                mapTypeValue = T3MapType.tencent;
              } else {
                mapTypeValue = T3MapType.amap;
              }

              List<T3RouteModel> routeList = [];
              //将路线模型重新映射
              for (var element in routes) {
                /// 路线id
                String? routeId = element.routeId;
                /// 预计行驶时间，单位：秒，降级为1分钟
                int duration = element.duration ?? 60;
                /// 起点和终点的距离，单位：米
                int distance = element.distance ?? 0;
                /// 道路费用，单位：元
                double tolls = element.tolls ?? 0;
                /// 红绿灯数量，单位：个
                int trafficLightCount = element.trafficLights ?? 0;
                /// 方案标签，表明方案特色
                String? tag = element.tags?.safeAccess(0);
                /// 方案标签，表明方案特色
                String? subTag = element.subTag;
                /// 路线数据坐标点串，用于传入Native进行处理，数据与coordinates保持一致
                String? polyline = element.polyline;
                /// 路线坐标点
                List<T3LocationCoordinate2D> coordinates = T3RouteModel.stringToCoordinate2D(polyline: polyline ?? '');
                /// 路况数据
                String? traffic = element.traffic;

                T3RouteModel routeModel = T3RouteModel(routeId: routeId, 
                                                       duration: duration, 
                                                       distance: distance, 
                                                       tolls: tolls, 
                                                       trafficLightCount: trafficLightCount, 
                                                       tag: tag,
                                                       subTag: subTag,
                                                       coordinates: coordinates, 
                                                       traffic: traffic,
                                                       provider: mapTypeValue);
                routeList.add(routeModel);
              }
              
              T3RouteResultModel resultModel = T3RouteResultModel(routes: routeList, provider: mapTypeValue);
              resultModel.navSessionId = value.navSessionId;

              return resultModel;
            } else {
              return null;
            }
          }
          else {
            return null;
          }
        }
        else {
          return null;
        }
      } else {
        return null;
      }
    } catch(e) {
      return null;
    }
  }
}

class _WalkRouteCalculateRequest extends T3GisMapApiRequest {
  @override
  String get path => "/notoken/ws/lbs/v2/direction/walking";

  /// 起点
  T3LocationCoordinate2D origin;
  /// 终点
  T3LocationCoordinate2D destination;

  _WalkRouteCalculateRequest({
    required this.origin,
    required this.destination,
  });

  @override
  Map<String, dynamic> toJson() {
    return {
      'origin':{
        'lat': origin.latitude,
        'lng': origin.longitude
      },
      'dest':{
        'lat': destination.latitude,
        'lng': destination.longitude
      },
      'noSteps' : false
    };
  }
}

class _DrivingRouteCalculateRequest extends T3GisMapApiRequest {
  @override
  String get path => "/notoken/ws/lbs/v2/route/eval/direction/driving";

  T3LocationCoordinate2D origin;
  T3LocationCoordinate2D dest;
  List<T3LocationCoordinate2D>? waypoints;
  double? departureTime;
  String? originPoiId;
  String? destPoiId;
  /// 起点areaCode
  String? areaCode;

  _DrivingRouteCalculateRequest({required this.origin, required this.dest, this.waypoints, this.departureTime, this.originPoiId, this.destPoiId, this.areaCode});

  @override
  Map<String, dynamic> toJson() {
    Map<String, dynamic> jsonData = {
      'origin':{
        'lat': origin.latitude,
        'lng': origin.longitude
      },
      'dest':{
        'lat': dest.latitude,
        'lng': dest.longitude
      },
      'noSteps' : false
    };

    final waypoints = this.waypoints;
    if (waypoints != null) {
      List<Map<String, double>> waypointsMapList = waypoints.map((e) => {
        "lat": e.latitude,
        "lng": e.longitude
      }).toList();
      jsonData["waypoints"] = waypointsMapList;
    }

    if (departureTime != null) {
      jsonData["departureTime"] = departureTime;
    }

    if (originPoiId != null) {
      jsonData["originPoiId"] = originPoiId;
    }

    if (destPoiId != null) {
      jsonData["destPoiId"] = destPoiId;
    }

    if (areaCode != null) {
      jsonData["adCode"] = areaCode;
    }

    return jsonData;
  }
}


@JsonSerializable(createToJson: false)
class _RouteContainerTransformModel {
  
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? supplier;

  @JsonKey()
  List<_RouteTransformModel>? routes;

  _RouteContainerTransformModel();

  factory _RouteContainerTransformModel.fromJson(dynamic json) => _$RouteContainerTransformModelFromJson(json);
}

@JsonSerializable(createToJson: false)
class _RouteTransformModel {
  ///路线id，用于下单时路线绑定
  @JsonKey()
  String? routeId;
  /// 路线标签
  @JsonKey()
  List<String>? tags;
  /// 路线行驶距离，单位米
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? distance;
  /// 路线行驶时间，单位秒
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? duration;
  /// 道路费用
  @JsonKey(fromJson: DoubleUtils.dynamicToNullDouble)
  double? tolls;
  /// 红绿灯数量
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? trafficLights;
  /// 路线数据
  @JsonKey()
  List<_StepTransformModel>? steps;
  /// 路况数据
  @JsonKey()
  String? traffic;

  _RouteTransformModel();

  factory _RouteTransformModel.fromJson(Map<String, dynamic> json) => _$RouteTransformModelFromJson(json);
}

@JsonSerializable(createToJson: false)
class _StepTransformModel {
  @JsonKey()
  String? polyline;

  _StepTransformModel();

  factory _StepTransformModel.fromJson(Map<String, dynamic> json) => _$StepTransformModelFromJson(json);
}

@JsonSerializable(createToJson: false)
class _DriverRouteContainerTransformModel {
  /// 导航算路ID（只有腾讯地图时会返回，后面路线绑定需要传入）
  @JsonKey()
  String? navSessionId;

  /// 地图供应商，参考 MapType
  @JsonKey()
  int? supplier;

  @JsonKey()
  List<_DriverRouteTransformModel>? routes;

  _DriverRouteContainerTransformModel();

  factory _DriverRouteContainerTransformModel.fromJson(dynamic json) => _$DriverRouteContainerTransformModelFromJson(json);
}

@JsonSerializable(createToJson: false)
class _DriverRouteTransformModel {
  ///路线id，用于下单时路线绑定
  @JsonKey()
  String? routeId;
  /// 路线标签
  @JsonKey()
  List<String>? tags;
  /// 路线子标签
  @JsonKey()
  String? subTag;

  /// 路线行驶距离，单位米
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? distance;
  /// 路线行驶时间，单位秒
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? duration;
  /// 道路费用
  @JsonKey(fromJson: DoubleUtils.dynamicToNullDouble)
  double? tolls;
  /// 红绿灯数量
  @JsonKey(fromJson: IntUtils.dynamicToNullInt)
  int? trafficLights;
  /// 路线的坐标点串
  @JsonKey()
  String? polyline;
  /// 路况数据
  @JsonKey()
  String? traffic;

  _DriverRouteTransformModel();

  factory _DriverRouteTransformModel.fromJson(dynamic json) => _$DriverRouteTransformModelFromJson(json);

}